/**
 * This is is a cache prefetch test with random memory access.
 */
#include <stdlib.h>
#include <stdio.h>
#include "misc.h"

#ifndef TSZ
#define TSZ (100*1024*1024)
#endif

#define PF_READ 0

struct data_struct {
	int a;
	int b;
	int c;
	int d;
};

int prefetch;
int sum=0;
#define LOOP 10000000

static inline int _cal(struct data_struct *d) {
	int tmp;

	tmp = d->a * d->b + d->c * d->d;
	tmp = tmp/1024;
	tmp += tmp*d->a - d->d;
	return tmp + d->a * d->b + d->c * d->d;
}

void calpf(void *d) {
	struct data_struct * data = d;
	int i, r, rn;

	r = rand()%TSZ;
	for(i=0; i<LOOP; i++) {
		rn = rand()%TSZ;
		__builtin_prefetch(&data[rn], PF_READ, 3);
		sum += _cal(&data[r]);
		r = rn;
	}

}

void calnopf(void *d) {
	struct data_struct * data = d;
	int i, r, rn;

	r = rand()%TSZ;
	for(i=0; i<LOOP; i++) {
		rn = rand()%TSZ;
		sum += _cal(&data[r]);
		r = rn;
	}

}

int main(void) {
	int i, tmp;
	struct data_struct * data = malloc(sizeof(*data)*TSZ);

	DIE_IF(!data, "malloc fail\n");

	// init data
	for (i=0; i<TSZ; i++) {
		tmp = rand();
		data[i].a = tmp+1;
		data[i].b = tmp-2;
		data[i].c = tmp*3;
		data[i].d = tmp/4;
	}
	
	// try some times
	for (i=0; i<3; i++) {
		MEASURE_TIME(calpf, data);
		MEASURE_TIME(calnopf, data);
	}

	free(data);
	return sum;
}
